package com.hjk.common.utils.check;

import com.hjk.common.utils.lambda.Streams;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 校验工具类
 *
 * @author huangjunkai
 * @version 1.0
 * @date 2020/09/16
 */
public class ValidatorUtils {

    // 获取Validator实例
    ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
    Validator validator = factory.getValidator();

    /**
     * 获取校验后的错误信息
     *
     * @param validator Validator
     * @param t         校验的实体
     * @param <T>       泛型
     * @return 错误信息或者null
     */
    public static <T> Optional validateToMessages(Validator validator, T t) {
        Set<ConstraintViolation<T>> errorSet = validator.validate(t);
        return Check.isNotEmpty(errorSet) ? Optional.of(Streams.toSet(errorSet, ConstraintViolation::getMessage)) : Optional.empty();
    }

    /**
     * 获取校验后的错误信息
     *
     * @param validator Validator
     * @param list      校验的集合
     * @param <T>       泛型
     * @return 错误信息或者null
     */
    public static <T> Optional validateToMessages(Validator validator, List<T> list) {
        Check.checkIsNotEmpty(list, "注解校验的集合不能为空");
        Set<Set<ConstraintViolation<T>>> errorInfoSet = list.stream()
                .map(m -> validator.validate(m)).filter(Check::isNotEmpty)
                .collect(Collectors.toSet());

        Set<String> set = null;
        if (Check.isNotEmpty(errorInfoSet)) {
            set = errorInfoSet.stream()
                    .flatMap(Collection::stream)
                    .map(ConstraintViolation::getMessage)
                    .collect(Collectors.toSet());
        }
        return Optional.ofNullable(set);
    }

    /**
     * @param validator Validator
     * @param list      集合外层
     * @param mapper    集合里面的集合
     * @param <T>       泛型
     * @return 错误信息或者null
     */
    public static <T> Optional validateToMessages(Validator validator, List<T> list, Function<? super T, Collection> mapper) {
        //第三层 validator注解校验 StandardPayBillDetailQo
        Set<Set<ConstraintViolation<Object>>> errorInfoSet = (Set<Set<ConstraintViolation<Object>>>) list.stream()
                .map(mapper)
                .flatMap(Collection::stream)
                .map(m -> validator.validate(m))
                .filter(Check::isNotEmpty)
                .collect(Collectors.toSet());

        Set<String> set = null;
        if (Check.isNotEmpty(errorInfoSet)) {
            set = errorInfoSet.stream()
                    .flatMap(Collection::stream)
                    .map(ConstraintViolation::getMessage)
                    .collect(Collectors.toSet());
        }
        return Optional.ofNullable(set);

    }

}



